/* 职责链模式 */

#[derive(Clone, Copy)]
enum LogLevel {
    INFO,
    WARN,
    DEBUG,
    ERROR
}


trait Logger {
    fn write_log(&self, msg: &str, level: LogLevel);
}


struct StdLogger {}

impl Logger for StdLogger {
    fn write_log(&self, msg: &str, level: LogLevel) {
        println!("[StdLogger] : {}", msg);
    }
}

struct FileLogger{
    filename: String
}

impl Logger for FileLogger {
    fn write_log(&self, msg: &str, level: LogLevel) {
        println!("[File {}] : {}", self.filename, msg);
    }
}

enum Chain {
    Node(Box<dyn Logger>, Box<Chain>),
    Nil
}

impl Chain {
    fn write_log(&self, msg: &str, level: LogLevel){
        match &self {
            Chain::Node(a, b) => {
                println!("匹配Node");
                a.write_log(msg, level);
                b.write_log(msg, level);
            },
            Chain::Nil => {
                println!("结束");
            }
        }
    }
}

#[cfg(test)]
mod tests{
    use super::*;
    use super::Chain::{Node, Nil};

    #[test]
    fn test_chain_of_responsibility_1() {
        let std_logger = StdLogger{};
        let file_1 = FileLogger{
            filename: String::from("output.log")
        };
        let file_2 = FileLogger{
            filename: String::from("20230101.log")
        };

        let logger = Node(Box::new(std_logger), Box::new(Nil));
        let logger = Node(Box::new(file_1), Box::new(logger));
        let logger = Node(Box::new(file_2), Box::new(logger));

        logger.write_log(&String::from("测试"), LogLevel::INFO{});
    }
}